/*******************************************************************************
 * Copyright (c) 2007 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/

package com.cea.papyrus.extensionpoints.dnd.parsing;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;

import com.cea.papyrus.extensionpoints.dnd.Activator;
import com.cea.papyrus.extensionpoints.dnd.parsing.ExtensionIds;
import com.cea.papyrus.extensionpoints.dnd.utils.IFilter;

/**
 * 
 */
public class DNDFilter extends AbstractExtensionPoint {
	

	/**
	 * Static list (created once) of the DNDFilters found after
	 * reading extensions.
	 */
	private static DNDFilter[] DNDFilters;
	
	public final IConfigurationElement	configElement;
	
	public final int ordinal;
	
	/**
	 * Attributes from the extension
	 */
	private final String id;
	private final String description;
	private final String filter;
		
	private boolean dndFilterRetrieved = false;
	private IFilter dndFilterInstance = null;
	
	/**
	 * Retrieve dnd filters found in plugins
	 * @return the {@link DNDFilter}s
	 */
	public static DNDFilter[] getDNDFilters() {
				
		if (DNDFilters != null) {
			return DNDFilters;
		}
		
		List<DNDFilter> filters = new ArrayList<DNDFilter>();
						
		// Reading data from plugins
		IConfigurationElement[] configElements = 
			Platform.getExtensionRegistry().getConfigurationElementsFor(ExtensionIds.FILTER_EXTENSION_ID);
		
		// Read configuration elements for the current extension
		for (int j = 0 ; j < configElements.length ; j++) {
			DNDFilter proxy = parseProfileExtension(configElements[j], filters.size());

			if (proxy != null) {
				filters.add(proxy);
			}
		} // end of configElements loop	
		
		DNDFilters = filters.toArray(new DNDFilter[filters.size()]);
		return DNDFilters;
	}
	
	/**
	 * 
	 * 
	 * @param ordinal 
	 * @param configElt 
	 * 
	 * @return 
	 */
	private static DNDFilter parseProfileExtension(IConfigurationElement configElt, int ordinal) {
		
		if (!configElt.getName().equals(ExtensionIds.TAG_DND_FILTER)) {
			return null;
		}
		
		try {
			return new DNDFilter(configElt, ordinal);
		} catch (Exception e) {
			
			String name = configElt.getAttribute(ExtensionIds.ATT_ID);
			if (name == null) {
				name = "[missing id attribute]";
			}
			String msg = "Failed to load dnd filter with id "
							+ name + " in "
							+ configElt
								.getDeclaringExtension()
								.getExtensionPointUniqueIdentifier();
			
			Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, msg));
			return null;
		}
	}
	
	/**
	 * 
	 * 
	 * @param ordinal 
	 * @param configElt 
	 */
	public DNDFilter(IConfigurationElement configElt, int ordinal) {
		this.configElement = configElt;
		this.ordinal = ordinal;
		
		id = 
			getAttribute(configElt, ExtensionIds.ATT_ID, "undefined", true);
		description = 
			getAttribute(configElt, ExtensionIds.ATT_DESC, "", false);
		filter = 
			getAttribute(configElt, ExtensionIds.ATT_FILTER, "undefined", true);
	}
	
	/**
	 * Default constructor.
	 * 
	 * @param id
	 */
	public DNDFilter(String id) {
		this.configElement = null;
		this.ordinal = -1;
		
		this.id = id;
		this.description = "";
		this.filter = "";
	}
	
	/**
	 * Try to retrieve and instantiate the filter
	 * @return
	 */
	private IFilter getDNDFilterInstance() {

		try {
			IFilter filterInstance = null;
			if (filter != null) {

				filterInstance = 
					(IFilter) configElement.createExecutableExtension(ExtensionIds.ATT_FILTER);
			}
			
			return filterInstance;
			
		} catch (Exception e) {
			IStatus status =
				new Status(
						IStatus.ERROR,
						Activator.PLUGIN_ID,
						"Unable to instantiate filter class.");
			Activator.getDefault().getLog().log(status);
			return null;
		}
	}
	
	/**
	 * Public accessor for Filter instance
	 * The instance is retrieved once using getDNDFilterInstance()
	 * @return the filter instance
	 */
	public IFilter getDNDFilter() {
		if (dndFilterRetrieved) {
			return dndFilterInstance;
		}
		dndFilterRetrieved = true;
		dndFilterInstance = getDNDFilterInstance();
		
		return dndFilterInstance;
	}

	public String getId() {
		return id;
	}

	public String getDescription() {
		return description;
	}
}
